<template>
    <div class="tableRow">
        <el-row class="select-list" v-permission="'system:user:query'">
            <el-form :inline="true" ref="selectForm" :label-position="'right'" label-width="80px"
                     :model="selectFormModel" size="mini">
                <el-form-item label="用户名" prop="userName">
                    <el-input v-model="selectFormModel.userName" placeholder="用户名" style="width: 200px" clearable
                              @keyup.enter.native="onSearch"/>
                </el-form-item>
                <el-form-item label="手机号码" prop="phoneNumber">
                    <el-input v-model="selectFormModel.phoneNumber" placeholder="手机号码" style="width: 200px" clearable
                              @keyup.enter.native="onSearch"/>
                </el-form-item>
                <el-form-item label="性别" prop="sex">
                    <el-select value="" v-model="selectFormModel.sex" placeholder="性别" style="width: 200px">
                        <el-option label="男" value="0"/>
                        <el-option label="女" value="1"/>
                        <el-option label="保密" value="2"/>
                    </el-select>
                </el-form-item>
                <el-form-item label="用户状态" prop="status">
                    <el-select value="" v-model="selectFormModel.status" placeholder="用户状态" style="width: 200px">
                        <el-option label="正常" value="0"/>
                        <el-option label="停用" value="1"/>
                    </el-select>
                </el-form-item>
                <el-form-item>
                    <el-button type="primary" icon="el-icon-search" size="mini" plain round @click="onSearch">搜索
                    </el-button>
                    <el-button type="warning" icon="el-icon-refresh" size="mini" plain round
                               @click="onRefreshSelectForm()">重置
                    </el-button>
                </el-form-item>
            </el-form>
        </el-row>
        <el-row class="toolbar">
            <el-button type="primary" icon="el-icon-plus" size="mini" plain @click="handleAdd"
                       v-permission="'system:user:add'">
                新增
            </el-button>
            <el-button type="info" icon="el-icon-edit" :disabled="dialog.isBatchEditDisabled" size="mini" plain
                       @click="handleEdit" v-permission="'system:user:edit'"> 编辑
            </el-button>
            <el-button type="danger" icon="el-icon-delete" :disabled="dialog.isBatchRemoveDisabled" size="mini" plain
                       @click="handleBatchDelete" v-permission="'system:user:remove'"> 删除
            </el-button>
            <el-button type="success" icon="el-icon-upload" size="mini" plain @click="handleImport"
                       v-permission="'system:user:import'"> 导入
            </el-button>
            <el-button type="warning" icon="fa fa-download" size="mini" plain @click="handleExport"
                       v-permission="'system:user:export'"> 导出
            </el-button>
        </el-row>
        <data-table ref="dataTable"
                    :api="getUserList"
                    :options="options"
                    :pagination.sync="page"
                    :columns="columns"
                    :operates="operates"
                    :query="selectFormModel"
                    @handleSelectionChange="handleSelectionChange"
        />

        <transition name="el-fade-in">
            <el-dialog :title="dialog.title" :visible.sync="dialog.dialogFormVisible"
                       :modal-append-to-body="false"
                       :destroy-on-close="false"
                       @close="closeDialog"
                       width="600px">
                <el-form :model="userModel" ref="userForm" label-width="100px" :rules="userFormRules" size="small ">
                    <el-form-item label="用户名" prop="userName">
                        <el-input v-model="userModel.userName" placeholder="用户名" :disabled="dialog.isEdit"/>
                    </el-form-item>
                    <el-form-item label="姓名" prop="name">
                        <el-input v-model="userModel.name" placeholder="姓名"/>
                    </el-form-item>

                    <el-form-item label="部门" prop="deptId">
                        <!--el-tree-select  文档地址 https://ayiaq1.github.io/el-tree-select/website/#/components/ElTreeSelect-->
                        <el-tree-select v-model="userModel.deptId" :selectParams="dialog.selectParams"
                                        :treeParams="dialog.treeParams"
                                        @searchFun="searchFun" ref="treeSelect"/>
                    </el-form-item>

                    <el-form-item label="角色" prop="roleIds">
                        <el-select value="" v-model="userModel.roleIds" multiple filterable clearable placeholder="角色">
                            <el-option
                                    v-for="item in dialog.roles"
                                    :key="item.id"
                                    :label="item.roleName"
                                    :value="item.id">
                            </el-option>
                        </el-select>
                    </el-form-item>

                    <el-form-item label="岗位" prop="postIds">
                        <el-select value="" v-model="userModel.postIds" multiple filterable clearable placeholder="岗位">
                            <el-option
                                    v-for="item in dialog.posts"
                                    :key="item.id"
                                    :label="item.postName"
                                    :value="item.id">
                            </el-option>
                        </el-select>
                    </el-form-item>
                    <el-form-item label="状态" prop="status">
                        <el-switch v-model="userModel.status" active-color="#13ce66" inactive-color="#ff4949"
                                   active-text="正常"
                                   inactive-text="停用"
                                   active-value="0"
                                   inactive-value="1"/>
                    </el-form-item>
                    <el-form-item label="邮箱" prop="email">
                        <el-input v-model="userModel.email" placeholder="邮箱"/>
                    </el-form-item>
                    <el-form-item label="手机" prop="phoneNumber">
                        <el-input v-model="userModel.phoneNumber" prefix-icon="el-icon-phone"
                                  placeholder="手机"/>
                    </el-form-item>
                    <el-form-item label="性别" prop="sex">
                        <el-select value="" v-model="userModel.sex" placeholder="性别">
                            <el-option label="男" value="0"/>
                            <el-option label="女" value="1"/>
                            <el-option label="保密" value="2"/>
                        </el-select>
                    </el-form-item>
                    <el-form-item label="备注" prop="remark">
                        <el-input v-model="userModel.remark" placeholder="备注" maxlength="100"/>
                    </el-form-item>
                </el-form>
                <div slot="footer" class="dialog-footer">
                    <el-button @click="dialog.dialogFormVisible=false" size="medium">取 消</el-button>
                    <el-button type="primary" @click="submitForm" size="medium">确 定</el-button>
                </div>
            </el-dialog>
        </transition>

        <transition name="el-fade-in">
            <el-dialog :title="dialog.title" :visible.sync="dialog.dialogImportVisible"
                       :modal-append-to-body="false"
                       :destroy-on-close="false"
                       custom-class="body-wrapper"
                       @close="closeUploadDialog"
                       width="500px">

                <el-upload
                        drag
                        ref="upload"
                        :action="src"
                        :show-file-list="true"
                        :auto-upload="false"
                        :headers="headers"
                        accept=".xls,.xlsx"
                        :on-success="uploadSuccess"
                        :on-exceed="handleExceed"
                        :on-error="uploadError"
                        :limit="1"
                >
                    <i class="el-icon-upload"/>
                    <div class="el-upload__text">将文件拖到此处，或<em>点击上传</em></div>

                    <div class="el-upload__tip" slot="tip">
                        <el-alert
                                title="只能上传xls/xlsx文件"
                                type="warning"
                                show-icon>
                        </el-alert>
                        <br/>
                        <el-alert type="info"
                                  show-icon
                                  :closable="false">
                            <span>没有模板？ 点击&nbsp;<a href="#" @click="downloadTemplate">下载模板</a></span>
                        </el-alert>
                    </div>
                </el-upload>

                <div slot="footer" class="dialog-footer">
                    <el-button @click="dialog.dialogImportVisible=false" size="medium">取 消</el-button>
                    <el-button type="primary" @click="submitUpload" size="medium">确 定</el-button>
                </div>
            </el-dialog>
        </transition>
    </div>
</template>
<script lang="ts">
  //https://github.com/kaorun343/vue-property-decorator
  import {Component, Ref, Vue} from 'vue-property-decorator';
  import DataTable from '@/components/DataTable/DataTable.vue';
  import {
    addUser,
    checkEmailUnique,
    checkPhoneUnique,
    checkUserNameUnique,
    downloadUserImportTemplate,
    exportUser,
    getUserList,
    getUserPost,
    getUserRole,
    removeUser,
    resetPwd,
    updateUser
  } from '@/api/user';
  import {deptTreeSelectData} from '@/api/dept';
  import {getPostList} from '@/api/post';
  import {getRoleList} from '@/api/role';
  import axios from 'axios';
  import store from '@/store';
  import {validateForm} from '@/utils';

  @Component({components: {DataTable}})
  export default class User extends Vue {
    private getUserList: Function = getUserList;
    @Ref('userForm') private userForm: any;
    @Ref('selectForm') private selectForm: any;
    @Ref('treeSelect') private treeSelect: any;
    @Ref('dataTable') private dataTable: any;
    @Ref('upload') private upload: any;

    get src() {
      return process.env.VUE_APP_BASE_API + '/system/user/import';
    }

    headers: any = {
      'Authorization': store.getters.token
    };

    columns: any = [
      {label: 'ID', prop: 'id', sortable: 'custom'},
      {label: '用户名', prop: 'userName', sortable: 'custom'},
      {label: '姓名', prop: 'name', sortable: 'custom'},
      {
        label: '部门', prop: 'dept', formatter: function (row: any, column: any) {
          if (row && row.dept && row.dept.deptName) {
            return row.dept.deptName;
          } else {
            return '无';
          }
        }
      },
      {label: '邮箱', prop: 'email', sortable: 'custom'},
      {label: '手机', prop: 'phoneNumber', sortable: 'custom'},
      {
        label: '性别', prop: 'sex', sortable: 'custom', formatter: function (row: any, column: any) {
          if (row && row.sex === '0') {
            return '男';
          } else if (row && row.sex === '1') {
            return '女';
          } else {
            return '保密';
          }
        }
      },
      {
        label: '状态', prop: 'status', sortable: 'custom', render: function (createElement: any, row: any) {
          if (row && row.row && row.row.status === '0') {
            return createElement('el-tag', {
                attrs: {
                  type: 'success'
                }
              }, ['正常']
            );
          } else if (row && row.row && row.row.status === '1') {
            return createElement('el-tag', {
                attrs: {
                  type: 'warning'
                }
              }, ['停用']
            );
          } else {
            return createElement('el-tag', {
                attrs: {
                  type: 'danger'
                }
              }, ['未知']
            );
          }
        }
      },
      {label: '创建时间', prop: 'createTime', sortable: 'custom', width: 160},
      {label: '备注', prop: 'remark', sortable: 'custom'}
    ];

    // table 的参数
    options: any = {
      stripe: true, // 是否为斑马纹 table
      loading: false, // 是否添加表格loading加载动画
      highlightCurrentRow: true, // 是否支持当前行高亮显示
      multipleSelect: true, // 是否支持列表项选中功能
    };


    // 分页参数
    page: any = {
      pageNum: 1,
      pageSize: 10,
      pageArray: [10, 20, 50, 100]
    };

    //按钮操作组
    operates: any = {
      title: '操作',
      width: 'auto',
      fixed: 'right',
      list: [
        {
          label: '编辑',
          type: 'warning',
          icon: 'el-icon-edit',
          plain: true,
          disabled: (index: any, row: any) => {
            return row && row.id === 1;
          },
          permission: 'system:user:edit',
          method: (index: any, row: any) => {
            this.handleEdit(index, row);
          }
        },
        {
          label: '删除',
          type: 'danger',
          icon: 'el-icon-delete',
          plain: true,
          disabled: (index: any, row: any) => {
            return row && row.id === 1;
          },
          permission: 'system:user:remove',
          method: (index: any, row: any) => {
            this.handleDelete(index, row);
          }
        },
        {
          label: '重置',
          type: 'primary',
          icon: 'el-icon-key',
          plain: true,
          disabled: (index: any, row: any) => {
            return row && row.id === 1;
          },
          permission: 'system:user:edit',
          method: (index: any, row: any) => {
            this.handleReset(index, row);
          }
        }
      ]
    };
    selectFormModel: any = {
      userName: '',
      status: '',
      phoneNumber: '',
      sex: '',
    };
    dialog: any = {
      dialogFormVisible: false,
      dialogImportVisible: false,
      title: '对话框',
      isEdit: false,
      isBatchEditDisabled: true,
      isBatchRemoveDisabled: true,
      formData: {},
      selectParams: {
        clearable: true,
        placeholder: '请选择部门'
      },
      treeParams: {
        clickParent: true,
        filterable: true,
        accordion: true,
        data: [],
        props: {
          children: 'children',
          label: 'label',
          disabled: 'disabled',
          value: 'id'
        }
      }
    };

    userModel: any = {
      userName: '',
      name: '',
      email: '',
      phoneNumber: '',
      sex: '',
      deptId: '',
      roleIds: [],
      status: 0,
      remark: '',
      postIds: []
    };
    userFormRules: any = {
      userName: [
        {required: true, message: '用户名不能为空', trigger: ['blur', 'change']},
        {
          required: true,
          pattern: /^[a-zA-Z0-9_]*$/,//可以写正则表达式
          message: '用户名只能是字母或者数字',
          trigger: ['blur', 'change']
        },
        {validator: this.validateUserNameUnique, trigger: 'blur'}
      ],
      name: [
        {required: true, message: '姓名不能为空', trigger: ['blur', 'change']}
      ],
      email: [
        {required: true, message: '邮箱不能为空', trigger: ['blur', 'change']},
        {type: 'email', message: '请输入正确的邮箱地址', trigger: ['blur', 'change']},
        {validator: this.validateEmailUnique, trigger: 'blur'}
      ],
      phoneNumber: [
        {required: true, message: '手机号码不能为空', trigger: 'blur'},
        {
          required: true,
          pattern: /^1[345678]\d{9}$/,//可以写正则表达式
          message: '目前只支持中国大陆的手机号码',
          trigger: ['blur', 'change']
        },
        {validator: this.validatePhoneUnique, trigger: 'blur'}
      ],
      sex: [
        {required: true, message: '性别不能为空', trigger: ['blur', 'change']}
      ]
    };

    /*验证用户名是否唯一*/
    validateUserNameUnique(rule: any, value: any, callback: any) {
      checkUserNameUnique({
        userName: value,
        id: this.userModel.id
      }).then((res: any) => {
        if (res.data && res.data === '0') {
          callback();
        } else {
          callback(new Error('用户名已经存在'));
        }
      }).catch((err: any) => {
        console.log(err);
        callback(new Error('用户名已经存在'));
      })
    }

    /*验证手机号码是否唯一*/
    validatePhoneUnique(rule: any, value: any, callback: any) {
      checkPhoneUnique({
        phoneNumber: value,
        id: this.userModel.id
      }).then((res: any) => {
        if (res.data && res.data === '0') {
          callback();
        } else {
          callback(new Error('手机号码已经存在'));
        }
      }).catch((err: any) => {
        console.log(err);
        callback(new Error('手机号码已经存在'));
      })
    }

    /*验证邮箱是否唯一*/
    validateEmailUnique(rule: any, value: any, callback: any) {
      checkEmailUnique({
        email: value,
        id: this.userModel.id
      }).then((res: any) => {
        if (res.data && res.data === '0') {
          callback();
        } else {
          callback(new Error('邮箱已经存在'));
        }
      }).catch((err: any) => {
        console.log(err);
        callback(new Error('邮箱已经存在'));
      })
    }

    handleEdit(index: number, row: any): void {
      //编辑
      this.userModel = Object.assign({}, row || this.dialog.formData[0]);
      this.userModel.dept = [];
      this.dialog.title = '编辑用户';
      this.dialog.isEdit = true;
      const id = (row && row.id) ? row.id : this.dialog.formData[0].id;

      axios.all(
        [
          getUserRole({'id': id}),
          deptTreeSelectData(),
          getUserPost({'id': id})
        ]
      ).then(axios.spread((role: any, dept: any, post: any) => {
        if (role.data) {
          this.userModel.roleIds = role.data.roleIds;
          this.dialog.roles = role.data.roles;
        }

        if (this.userModel && this.userModel.roleIds === null) {
          this.userModel.roleIds = [];
        }
        if (dept.data) {
          this.dialog.treeParams.data = dept.data;
        }

        if (post.data) {
          this.userModel.postIds = post.data.postIds;
          this.dialog.posts = post.data.posts;
        }

        this.dialog.dialogFormVisible = true;
      })).catch((e) => {
        console.log(e);
      });
    }

    handleAdd(): void {
      //打开新增
      this.dialog.title = '新增用户';
      this.dialog.isEdit = false;

      axios.all([getRoleList({'status': 0}), deptTreeSelectData(), getPostList({'status': 0})])
        .then(axios.spread((role: any, dept: any, post: any) => {
          this.dialog.roles = role.rows;
          this.dialog.treeParams.data = dept.data;
          this.dialog.posts = post.rows;
          this.dialog.dialogFormVisible = true;
        })).catch((e) => {
        console.log(e);
      });
    }

    handleBatchDelete(): void {
      //删除
      this.$confirm('确定要删除选定用户？', '警告', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).then(() => {
        const ids: Array<any> = [];
        this.dialog.formData.forEach((item: any, index: number) => {
          ids[index] = item.id;
        });
        return removeUser({'ids': ids});
      }).then((response: any) => {
        this.dataTable.refresh();
        this.$message.success(response.msg);
      }).catch((e) => {
        console.log(e);
      });
    }

    searchFun(value: any): void {
      this.treeSelect.filterFun(value);
    }

    onSearch(): void {
      this.dataTable.refresh();
    }

    onRefreshSelectForm(): void {
      //恢复搜索默认信息
      this.selectForm.resetFields();
      this.onSearch();
    }

    closeDialog(): void {
      this.$nextTick(() => {
        this.dialog.treeParams.data = [];
        this.reset();
      });
    }

    submitForm(): void {
      this.userForm.validate((valid: boolean) => {
        if (valid) {
          this.userModel.roles = [];
          this.userModel.dept = [];
          this.userModel.posts = [];
          if (this.dialog.isEdit) {
            //编辑
            updateUser(this.userModel).then((response: any) => {
              this.dataTable.refresh();
              this.reset();
              this.dialog.dialogFormVisible = false;
              this.$message.success(response.msg);
            }).catch((e) => {
              console.log(e);
              validateForm(e.data, this.userForm, this.userFormRules);
            });
          } else {
            //新增
            addUser(this.userModel).then((response: any) => {
              this.dataTable.refresh();
              this.reset();
              this.dialog.dialogFormVisible = false;
              this.$message.success(response.msg);
            }).catch((e) => {
              console.log(e);
              validateForm(e.data, this.userForm, this.userFormRules);
            });
          }
        }
      });
    }

    handleDelete(index: number, row: any): void {
      //删除
      this.$confirm('确定要删除该用户？', '警告', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).then(() => {
        return removeUser({'ids': [row.id]});
      }).then((response: any) => {
        this.dataTable.refresh();
        this.$message.success(response.msg);
      }).catch((e) => {
        console.log(e);
      });
    }

    handleReset(index: number, row: any): void {
      //删除
      this.$confirm('确定要重置该用户的登录密码吗？', '警告', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).then(() => {
        return resetPwd({'id': row.id});
      }).then((response: any) => {
        this.dataTable.refresh();
        this.$message.success(response.msg);
      }).catch((e) => {
        console.log(e);
      });
    }

    handleSelectionChange(val: any): void {
      //返回选中对象
      if (val) {
        this.dialog.isBatchRemoveDisabled = val.length <= 0;
        this.dialog.isBatchEditDisabled = val.length !== 1;
      }
      this.dialog.formData = val;
    }

    reset(): void {
      this.userModel = {
        userName: '',
        name: '',
        email: '',
        phoneNumber: '',
        sex: '',
        deptId: '',
        roleIds: [],
        status: 0,
        remark: '',
        postIds: []
      };
      (this as any).resetForm('userForm');
    }

    /*导出excel*/
    handleExport(): void {
      this.$confirm('确定要导出当前查询的所有用户信息吗？', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'info'
      }).then(() => {
        this.selectFormModel.pageNum = null;
        this.selectFormModel.pageSize = null;
        this.selectFormModel.orderByColumn = 'id';
        this.selectFormModel.isAsc = 'asc';

        return exportUser(this.selectFormModel);
      }).then((response: any) => {
        console.log(response);
        if (response && response.data) {
          (this as any).$download(response.data.fileName);
        }
      }).catch((e) => {
        console.log(e);
      });
    }

    /*下载用户导入模板*/
    downloadTemplate(): void {
      downloadUserImportTemplate().then((response: any) => {
        console.log(response);
        if (response && response.data) {
          (this as any).$download(response.data.fileName);
        }
      }).catch((e) => {
        console.log(e);
      });
    }

    /*打开导入对话框*/
    handleImport(): void {
      this.dialog.title = '用户导入';
      this.dialog.dialogFormVisible = false;
      this.dialog.dialogImportVisible = true;
    }

    /*上传*/
    submitUpload() {
      this.upload.submit();
    }

    /*上传成功*/
    uploadSuccess(res, file) {
      console.log(res);
      if (res.result) {//上传成功
        this.$message.success(`导入成功，${res.msg}`);
      } else {//上传失败
        this.$message.warning(`导入失败，${res.msg}`);
        this.upload.clearFiles();
      }
    }

    /*文件上传失败*/
    uploadError(res, file) {
      console.log(res.message);
      const result = JSON.parse(res.message);

      this.$message.error(`导入失败，${result.msg}`);
    }

    handleExceed(files, fileList) {
      this.$message.warning(`当前限制选择 3 个文件，本次选择了 ${files.length} 个文件，共选择了 ${files.length + fileList.length} 个文件`);
    }

    closeUploadDialog() {
      this.$nextTick(() => {
        this.upload.clearFiles();
      });
    }
  }
</script>

<style scoped lang="scss">
    a {
        color: #8c939d;

        &:hover {
            color: #b4bccc;
            text-decoration: underline;
        }
    }
</style>

